package com.imooc.coupon.executor;

import com.alibaba.fastjson.JSON;
import com.imooc.coupon.vo.CouponTemplateSDK;
import com.imooc.coupon.vo.GoodsInfo;
import com.imooc.coupon.vo.SettlementInfo;
import com.imooc.coupon.vo.TemplateRule;
import org.apache.commons.collections4.CollectionUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <h1>规则执行器抽象类, 定义通用方法</h1>
 * Created by Qinyi.
 */
public abstract class AbstractExecutor implements IRuleExecutor{

    /**
     * <h2>校验商品类型与优惠券是否匹配</h2>
     * 需要注意:
     * 1. 这里实现的单品类优惠券的校验, 多品类优惠券重载此方法
     * 2. 商品只需要有一个优惠券要求的商品类型去匹配就可以
     * */
    protected boolean isGoodTypeSatisfy(SettlementInfo settlement){
        // 结算商品列表
        Set<Integer> goodsTypes = settlement.getGoodsInfos()
                                        .stream()
                                        .map(GoodsInfo::getType)
                                        .collect(Collectors.toSet());
        // 优惠券商品类别
        List<Integer> couponGoodsTypes = JSON.parseObject(settlement.getCouponAndTemplateInfos()
                .get(0).getTemplate().getRule().getUsage().getGoodsType(),List.class);

        // 存在交集即可
        return CollectionUtils.isNotEmpty(CollectionUtils.intersection(goodsTypes,couponGoodsTypes));
    }

    /**
     * <h2>处理商品类型与优惠券限制不匹配的情况</h2>
     * @param settlement {@link SettlementInfo} 用户传递的结算信息
     * @param goodsSum 商品总价
     * @return {@link SettlementInfo} 已经修改过的结算信息, 或 null：表示商品类型与优惠券匹配
     * */
    protected SettlementInfo processGoodsTypeNotSatisfy(SettlementInfo settlement, double goodsSum){
        boolean isGoodsTypeSatisfy = isGoodTypeSatisfy(settlement);
        if(!isGoodsTypeSatisfy){
            settlement.setCost(goodsSum);
            settlement.setCouponAndTemplateInfos(Collections.emptyList());
            return settlement;
        }

        return null;
    }

    /**
     * <h2>商品总价</h2>
     * */
    protected double goodsCostSum(List<GoodsInfo> goodsInfos){
        return goodsInfos.stream().mapToDouble(g -> g.getPrice()*g.getCount())
                .sum();
    }

    /**
     * <h2>保留两位小数</h2>
     * */
    protected double retain2Decimals(double value) {

        return new BigDecimal(value).setScale(
                2, BigDecimal.ROUND_HALF_UP
        ).doubleValue();
    }

    /**
     * <h2>最小支付费用</h2>
     * */
    protected double minCost() {

        return 0.1;
    }

}





